/*
This exercise is designed to demonstrate why the atomicity guaranteed by opening
a file with the O_APPEND flag is necessary. Write a program that takes up to three
command-line arguments:
$ atomic_append filename num-bytes [x]
This file should open the specified filename (creating it if necessary) and append
num-bytes bytes to the file by using write() to write a byte at a time. By default, the
program should open the file with the O_APPEND flag, but if a third command-line
argument (x) is supplied, then the O_APPEND flag should be omitted, and instead the
program should perform an lseek(fd, 0, SEEK_END) call before each write(). Run
two instances of this program at the same time without the x argument to write
1 million bytes to the same file:
$ atomic_append f1 1000000 & atomic_append f1 1000000
Repeat the same steps, writing to a different file, but this time specifying the x
argument:
$ atomic_append f2 1000000 x & atomic_append f2 1000000 x
List the sizes of the files f1 and f2 using ls –l and explain the difference.
*/

/*
ans. O_APPEND works better because
-> Before each write(2), the file offset is positioned at the end of the file, as if with lseek(2).
-rwx------ 1 daniel daniel  2000 05-05 23:27 file
-rwx------ 1 daniel daniel  1119 05-05 23:27 file1
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h>

int
main (int argc, char *argv[])
{
  if (argc != 4 && argc != 5)
    return EXIT_FAILURE;

  const char *filename = argv[1];
  long long num_bytes = atoll (argv[2]);
  const char *data = argv[3];
  bool if_append = (!argv[4]) ? true : false;
  printf ("Parameters: %s %lld %d\n", filename, num_bytes, if_append);

  int fd;
  if (if_append)
    {
      if ((fd = open (filename, O_CREAT|O_WRONLY|O_APPEND, S_IRWXU)) == -1)
        return EXIT_FAILURE;

      while (num_bytes--)
        {
          if ((write (fd, data, 1)) == -1)
            return EXIT_FAILURE;
        }
    }
  else
    {
      if ((fd = open (filename, O_CREAT|O_WRONLY, S_IRWXU)) == -1)
        return EXIT_FAILURE;

      while (num_bytes--)
        {
          if ((lseek (fd, 0, SEEK_END)) == -1)
            return EXIT_FAILURE;
          if ((write (fd, data, 1)) == -1)
            return EXIT_FAILURE;
        }
    }
  close (fd);
  return EXIT_SUCCESS;
}
